import xml.sax as sax
import os, zipfile, shutil, glob, json, re, time, base64
#$exec = 
#$exec = "java -jar tools/ddx.jar -o -D -r -d $ddx $file_dex";
#$exec = "dex2jar.bat ../../$file_dex";

FILE_UPLOAD_DIR = "./file_upload/"
REPORTS_DIR = "./static/reports/"

def getEtag(str_gtm_time):
	return '"'+base64.b64encode(str_gtm_time)+'"'

def getGtmTime(etag):
	return base64.b64decode(etag[1:len(etag)])

def getLastModifed(lugar):
	return time.strftime("%a, %d %b %Y %H:%M:%S GTM", time.gmtime(os.path.getmtime(lugar)))

def findPackages(lugar):
	antes = os.getcwd()
	os.chdir(lugar)
	ret = _recurrenteFindPackages()
	os.chdir(antes)
	return ret

def _recurrenteFindPackages(pack=""):
	ret = {}
	files = glob.glob('*.*')
	for f in files:
		if os.path.isfile(f):
			(name, ext) = f.rsplit(".", 1)
			if ext == "ddx" or ext == "smali":
				if not pack in ret:
					ret[pack] = []
				ret[pack] += [name]

	files = glob.glob('*')
	antes = os.getcwd()
	for f in files:
		if os.path.isdir(f):
			os.chdir(f)
			npack = pack
			if pack != "":
				npack = pack+"."
			encontrados = _recurrenteFindPackages(npack+f)
			for key in encontrados:
				ret[key] = encontrados[key]
			os.chdir(antes)
	return ret

def findRecursos(lugar):
	if not os.path.isdir(lugar):
		return {}
	antes = os.getcwd()
	os.chdir(lugar)
	ret = _recurrenteFindRecursos()
	if os.path.isdir('./../assets'):
		os.chdir('./../assets')
		ret["assets"] = _recurrenteFindRecursos()
	if os.path.isdir('./../lib'):
		os.chdir('./../lib')
		ret["lib"] = _recurrenteFindRecursos()
	os.chdir(antes)
	
	return ret

__KEY_FICHEROS = "_ficheros_"
def _recurrenteFindRecursos():
	ret = {__KEY_FICHEROS:[]}
	files = glob.glob('*')
	antes = os.getcwd()
	for f in files:
		if os.path.isfile(f):
			ret[__KEY_FICHEROS] += [f]
		if os.path.isdir(f):
			os.chdir(f)
			ret[f] = _recurrenteFindRecursos()
			os.chdir(antes)
	return ret

class Public_xml(sax.handler.ContentHandler):
	def __init__(self, id=None):
		sax.handler.ContentHandler.__init__(self)
		self.id = id
		self.found = None

	def startElement(self, name, attrs):
		if not self.found and name == "public":
			if attrs.get("id") == self.id:
				self.found = attrs

	def getTypeName(self, dir_samples, id=None):
		if id: self.id = id
		ref = './values/public.xml'
		type = None
		res = None
		if os.path.isfile(dir_samples + ref):
			with open(dir_samples + ref, 'r') as fp:
				try:
					self.found = None
					sax.parseString(fp.read(), self)
					if self.found:
						type = self.found.get("type")
						res = self.found.get("name")
				except sax.SAXParseException, e:
					pass#TODO error
				fp.close()
		return (type, res)

class Resources_xml(sax.handler.ContentHandler):
	def __init__(self, found_name=None):
		sax.handler.ContentHandler.__init__(self)
		self.suported_types = ["string","dimen","integer","color","array"]
		self.extra_suport = ["string-array"]
		self.found_name = found_name
		self.found = None
		self.read_content = False
		self.array_mode = False

	def startElement(self, name, attrs):
		if not self.found and (name in self.suported_types or name in self.extra_suport):
			self.array_mode = (name.find("array") != -1)
			if attrs.get("name") == self.found_name:
				self.read_content = True
		if self.array_mode:
			self.read_content = (name=="item")

	def endElement(self, name):
		if self.array_mode and (name.find("array") != -1):
			self.array_mode = False
		self.read_content = False

	def characters(self, content):
		if self.read_content:
			if not self.found:
				self.found = ""
			if self.array_mode:
				self.found += content+","
			else:
				self.found = content

	def getValue(self, dir_samples, type, found_name=None):
		if found_name: self.found_name = found_name
		self.found = None
		link = None
		if type in self.suported_types:
			ref = './values/'+type+'s.xml'
			if os.path.isfile(dir_samples + ref):
				link = "@values/"+type+"s"
				with open(dir_samples + ref, 'r') as fp:
					try:
						sax.parseString(fp.read(), self)
					except sax.SAXParseException, e:
						#self.found = "Error"+ str(e)
						pass#TODO error
					fp.close()
		if type == "array":
			self.found = "["+self.found[:-1]+"]"
			pass
		return (self.found, link)

def getPathFromRecurso(sample_md5, key):
	if not isinstance(key, str) and not isinstance(key, unicode):
		return False
	dir_samples = REPORTS_DIR + sample_md5 +'/smali/res/'
	if not os.path.isdir(dir_samples):
		return False
	type = None
	res = None
	if key.startswith("@"):
		(type, res) = key[1:].split("/", 1)
	if key.startswith("0x"):
		pxml = Public_xml(key)
		(type, res) = pxml.getTypeName(dir_samples)

	if not type or not res or type in ["string","dimen","integer","color","array"]:
		return False
	elif type == "assets" or type == "raw":
		busca = REPORTS_DIR + sample_md5 + "/smali/"
		if type == "raw":
			busca += 'res/raw/'+res+".*";
		else:
			busca += 'assets/'+res+"*";
		encontrados = glob.glob(busca)
		if encontrados:
			return encontrados[0].replace('\\','/')#Eliminamos el ./ y pasamos a / y a Unix
		return False
	
	xml_file = dir_samples + type + "/" +res+".xml";
	if type.startswith("drawable"):
		busca = dir_samples + type
		#Puede estar en drawable, drawable-ldpi, drawable-mdpi o drawable-hdpi
		if(type == "drawable"): busca += "*"
		busca +="/"+res+".*"
		encontrados = glob.glob(busca)
		if encontrados:
			return encontrados[0].replace('\\','/')#Eliminamos el ./ y pasamos a / y a Unix
	elif os.path.isfile(xml_file):
		return xml_file#Eliminamos el ./ y pasamos a /
	return False


def getRecurso(sample_md5, key):
	ret = json.dumps({"unknow":key})
	if not isinstance(key, str) and not isinstance(key, unicode):
		return test
	dir_samples = REPORTS_DIR + sample_md5 +'/smali/res/'
	if not os.path.isdir(dir_samples):
		return ret
	type = None
	res = None
	if key.startswith("@"):
		(type, res) = key[1:].split("/", 1)
	if key.startswith("0x"):
		pxml = Public_xml(key)
		(type, res) = pxml.getTypeName(dir_samples)
		ret = json.dumps({"know":"@"+type+"/"+res})
	if not type or not res:
		return ret, type, res

	sxml = Resources_xml(res)
	if type == "drawable":
		#Puede estar en drawable, drawable-ldpi, drawable-mdpi o drawable-hdpi
		encontrados = glob.glob(dir_samples + "drawable*/"+res+".???")
		if not encontrados:
			encontrados = glob.glob(dir_samples + "drawable*/"+res+".9.png")
		if encontrados:
			link = encontrados[0][1:]#Eliminamos el ./ y pasamos a /
			if link.endswith(".png"):
				link = link.replace('\\','/')
				return json.dumps({"img":link})
			return json.dumps({"link":"@"+type+"/"+res})
	elif type in sxml.suported_types:
		(valor, link) = sxml.getValue(dir_samples, type)
		if valor:
			if type == "array":
				lista = valor.replace('"',"")[1:-1].split(",")
				valor = "[<br/>"
				for key in lista:
					info = json.loads(getRecurso(sample_md5,key))
					if "know" in info:
						valor += info["know"]+"<br/>"
					else:
						valor += key+"<br/>"
				valor += "]"
			ret = json.dumps({"know":valor})
		else:
			json.dumps({"link":link})
	elif os.path.isdir(dir_samples+ type) and os.path.isfile(dir_samples+ type+"/"+res+".xml"):
		ret = json.dumps({"link":"@"+type+"/"+res})
	return ret
